package com.five.mobile.interceptor;


import com.five.admin.dto.UserThreadLocalDto;
import com.five.admin.threadLocal.UserThreadLocal;
import com.five.core.exception.CustomerException;
import com.five.core.result.ResultEnum;


import com.five.core.utils.CheckMobile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.concurrent.TimeUnit;

/**
 * 认证拦截器
 */
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {

    public final static String TOKEN_KEY = "USER_TOKEN_KEY";
    //用户token过期时间
    public final static Integer TOKEN_EXPIRE = 60 * 60 * 2;
    //mobile 用户
    public static final String MOBILE_LOGGED_IN_KEY = "USER_MOBILE:LOGGED_IN";
    //pc 用户
    public static final String PC_LOGGED_IN_KEY = "USER_PC:LOGGED_IN";
    //mobile 最大用户
    public static final Long MAX_LOGIN_MOBILE_DEVICE = 3L;
    //pc 最大用户
    public static final Long MAX_LOGIN_PC_DEVICE = 3L;


    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String token = request.getHeader("token");
        System.err.println("token:"+token);
        if (token == null || token.isEmpty() || "null".equals(token)) {
            throw new CustomerException(ResultEnum.NO_USER_LOGIN);
        }

        //先从 redis 中判断当前用户的状态
        String userId = (String) redisTemplate.opsForValue().get(TOKEN_KEY + token);
        if (userId != null && userId.isEmpty()) {
            throw new CustomerException(ResultEnum.TOKEN_IS_NOT_EMPTY);
        }

        //获取用户信息
        String userAgent = request.getHeader("User-Agent");
        boolean isMobile = CheckMobile.check(userAgent); // 复用之前的设备判断工具
        String devicePrefix = isMobile ? MOBILE_LOGGED_IN_KEY : PC_LOGGED_IN_KEY;

        // 构建用户+设备的会话列表Key（与登录时一致）
        String userDeviceKey = devicePrefix +  userId;

        // 检查当前Token是否在该用户的会话列表中
        Long tokenCount = redisTemplate.opsForList().indexOf(userDeviceKey, token);
        if (tokenCount == null || tokenCount < 0) {
            // Token不在有效会话列表中（可能已被挤出或手动退出）
            throw new CustomerException(ResultEnum.TOKEN_EXPIRED_OR_LOGOUT);
        }

        // 延长Token有效期（活跃用户自动续期）
        redisTemplate.expire(TOKEN_KEY + token, TOKEN_EXPIRE, TimeUnit.SECONDS);
        redisTemplate.expire(userDeviceKey, TOKEN_EXPIRE, TimeUnit.SECONDS);

        UserThreadLocalDto userThreadLocalDto = new UserThreadLocalDto();
        if (userId != null) {
            userThreadLocalDto.setId(Long.parseLong(userId));
        }
        UserThreadLocal.set(userThreadLocalDto);
        return true;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        UserThreadLocal.remove();
    }
}
